<template>
  <div class="point-cloud-viewer">
    <!-- 渲染容器 -->
    <div ref="renderContainer" class="render-container"></div>
    <!-- 加载状态 -->
    <div v-if="loading" class="loading-mask">
      <div class="loading-text">加载点云数据中...</div>
    </div>
    <!-- 错误提示 -->
    <div v-if="error" class="error-message">
      <el-icon><WarningFilled /></el-icon>
      <span>{{ errorMessage }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { PLYLoader } from 'three/addons/loaders/PLYLoader.js'
import { WarningFilled } from '@element-plus/icons-vue'
import api from '@/auth/myaxios'

// 接收文物ID（用于请求点云数据）
const props = defineProps({
  relicId: {
    type: Number,
    required: true,
  },
})

// 状态管理
const renderContainer = ref<HTMLDivElement>(null)
const loading = ref(true)
const error = ref(false)
const errorMessage = ref('')
const pointSize = ref(0.5)

// Three.js核心对象
let scene: THREE.Scene, camera: THREE.Camera, renderer: THREE.WebGLRenderer
let controls: OrbitControls,
  pointCloud: THREE.Points | null = null

// 初始化场景
const initScene = () => {
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x1a1a1a)

  // 相机
  camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000)
  camera.position.z = 50

  // 渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setPixelRatio(window.devicePixelRatio)
  renderContainer.value?.appendChild(renderer.domElement)

  // 控制器
  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  controls.dampingFactor = 0.1
  controls.enableZoom = true
  controls.enablePan = true

  // 辅助坐标轴
  const axesHelper = new THREE.AxesHelper(10)
  scene.add(axesHelper)

  // 光源
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.6)
  scene.add(ambientLight)
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
  directionalLight.position.set(30, 50, 20)
  scene.add(directionalLight)
}

// 加载点云数据
const loadPointCloud = async () => {
  loading.value = true
  error.value = false
  errorMessage.value = ''

  try {
    const response = await api.get(`/api/relics/${props.relicId}/point-cloud/`, {
      responseType: 'arraybuffer',
    })

    // 解析PLY数据
    const loader = new PLYLoader()
    const geometry = loader.parse(response.data)
    console.log('点云数据解析成功，顶点数量:', geometry.attributes.position.count)

    // 创建材质（强制使用可见颜色，不依赖顶点颜色）
    const material = new THREE.PointsMaterial({
      size: 3, // 增大点大小，确保可见
      color: 0xffffff, // 亮绿色，与深色背景对比明显
      transparent: false, // 禁用透明度
      sizeAttenuation: false, // 所有点大小一致，不随距离衰减
    })
    // 创建点云对象
    if (pointCloud) scene.remove(pointCloud)
    pointCloud = new THREE.Points(geometry, material)
    scene.add(pointCloud)
    console.log('点云已添加到场景')

    // 计算点云边界盒
    const box = new THREE.Box3().setFromObject(pointCloud)
    const center = new THREE.Vector3()
    box.getCenter(center)
    const size = box.getSize(new THREE.Vector3())
    const maxDim = Math.max(size.x, size.y, size.z)

    // 设置相机位置（从斜上方观察）
    const cameraZ = Math.max(maxDim * 1.5, 10) // 确保相机与点云保持足够距离
    camera.position.set(center.x, center.y + cameraZ * 0.5, cameraZ) // 从斜上方观察
    camera.lookAt(center)
    controls.target.copy(center)
    controls.update() // 强制更新控制器

    console.log('相机已设置到合适位置')
  } catch (err) {
    error.value = true
    errorMessage.value = err instanceof Error ? err.message : '点云加载失败'
    console.error('点云加载错误:', err)
  } finally {
    loading.value = false
  }
}

// 控制方法

// 渲染循环
const animate = () => {
  requestAnimationFrame(animate)
  controls.update()
  renderer.render(scene, camera)
}

// 窗口适配
const handleResize = () => {
  if (!renderContainer.value) return
  const { clientWidth, clientHeight } = renderContainer.value
  camera.aspect = clientWidth / clientHeight
  camera.updateProjectionMatrix()
  renderer.setSize(clientWidth, clientHeight)
}

// 生命周期
onMounted(() => {
  if (renderContainer.value) {
    initScene()
    handleResize()
    window.addEventListener('resize', handleResize)
    animate()
    loadPointCloud()
  }
})

onMounted(async () => {
  if (renderContainer.value) {
    initScene()
    await nextTick()
    handleResize()
    // fallback：如果初次 clientHeight 仍为 0，再延迟一次
    setTimeout(() => {
      handleResize()
    }, 100)
    window.addEventListener('resize', handleResize)
    animate()
    loadPointCloud()
  }
})
</script>

<style scoped>
.point-cloud-viewer {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 500px;
}

.render-container {
  width: 100%;
  height: 100%;
}

.loading-mask {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.8);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 10;
}

.loading-text {
  margin-top: 16px;
  color: #666;
}

.error-message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #f56c6c;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 16px;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 4px;
  z-index: 10;
}

.controls {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 8px 16px;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  z-index: 5;
}

.slider-label {
  font-size: 12px;
  color: #666;
  width: 80px;
}

.el-slider {
  width: 200px;
}
.render-container {
  width: 100%;
  height: 600px; /* 临时固定一个高度看是否能显示 */
}
</style>
